package com.bj58.ecdata.calc.dbservice.service.impl;

import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import redis.clients.jedis.Tuple;

import com.bj58.ecdata.calc.dbservice.consts.Constant;
import com.bj58.ecdata.calc.dbservice.dao.InfoDao;
import com.bj58.ecdata.calc.dbservice.dao.ResumeAddDao;
import com.bj58.ecdata.calc.dbservice.dao.model.DataPoint;
import com.bj58.ecdata.calc.dbservice.dao.model.InfoModel;
import com.bj58.ecdata.calc.dbservice.dao.model.ResumeAddModel;
import com.bj58.ecdata.calc.dbservice.load.SpringUtils;
import com.bj58.ecdata.calc.dbservice.model.ResultObj;
import com.bj58.ecdata.calc.dbservice.model.ResultPoint;
import com.bj58.ecdata.calc.dbservice.service.BusslineEnum;
import com.bj58.ecdata.calc.dbservice.service.InfoService;
import com.bj58.ecdata.exception.BusinessException;
import com.bj58.ecdata.util.DateUtils;
import com.bj58.ecdata.util.JsonUtils;
import com.bj58.spat.scf.server.contract.annotation.ServiceBehavior;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

@ServiceBehavior
public class InfoServiceImpl  implements InfoService{
	Logger log = LoggerFactory.getLogger(InfoServiceImpl.class);
	private List<String> types;
	private List<String> divTypes = Lists.newArrayList();
	private InfoDao dao = SpringUtils.getInstance().getBean(InfoDao.class);
	private ResumeAddDao resumeAddDao = SpringUtils.getInstance().getBean(ResumeAddDao.class);

	public InfoServiceImpl() {
		types = Lists.newArrayList("infoNum");
	}

	@Override
	public String getDailySum(String platform, BusslineEnum bussline) {
		InfoModel model = new InfoModel();
		model.setTime(DateUtils.getTruncatedToday());
		model.setPlatform(StringUtils.isBlank(platform) ? null : platform );
		model.setBussline(bussline != null ? bussline.value() : null);

		long infoNum = dao.loadDailySum("infoNum", model);

		DataPoint dataPoint = new DataPoint();
		dataPoint.setTime(dao.getLatest());
		dataPoint.setValue(infoNum);
		return JsonUtils.toJson(dataPoint);
	}

	@Override
	public String getData(String type, String platform, BusslineEnum bussline, long time) {

		checkType(type);

		long endTime = dao.getLatest();
		List<InfoModel> params = createModels(time, endTime, Constant._2s, Constant._1h, platform, bussline);
		List<DataPoint> datas = dao.load(type, params, isDiv(type));
		Map<String, Object> result = Maps.newHashMap();
		result.put("data", datas);
		return JsonUtils.toJson(result);
	}

	@Override
	public String getDataTodayHourly(String type, String platform, BusslineEnum bussline) {

		checkType(type);

		long zeroTime = DateUtils.getTruncatedToday();
		long curTime = dao.getLatest();
		long endTime = DateUtils.truncateToHour(curTime) - Constant._1h;
		List<InfoModel> params = createModels(0, endTime, Constant._1h, endTime - zeroTime + Constant._1h, platform, bussline);
		List<DataPoint> datas = dao.loadHourly(type, params, isDiv(type));
		Map<String, Object> result = Maps.newHashMap();
		result.put("data", datas);
		return JsonUtils.toJson(result);
	}

	@Override
	public String getDataYesterdayHourly(String type, String platform, BusslineEnum bussline) {

		checkType(type);

		long endTime = DateUtils.getTruncatedToday() - Constant._1h;
		List<InfoModel> params = createModels(0, endTime, Constant._1h, Constant._1d, platform, bussline);
		List<DataPoint> datas = dao.loadHourly(type, params, isDiv(type));
		Map<String, Object> result = Maps.newHashMap();
		result.put("data", datas);
		return JsonUtils.toJson(result);
	}

	/**
	 * 某个业务线的TOP
	 */
	@Override
	public String getTopCateList(String platform, BusslineEnum bussline, int count) {
		if (count < 1) {
			count = 1;
		}
		ResultObj result = new ResultObj();
		result.setData(getTopCateData(platform, bussline, count));
		return JsonUtils.toJson(result);
	}
	
	/**
	 * 返回各个业务线(加上简历) 的TOP N 以及 每个业务线当前总量
	 */
	@Override
	public String getTopCateList(int count) {
		if (count < 1) {
			count = 1;
		}
		Map<String, Map<String, Object>> resultMap = Maps.newHashMap();
		
		InfoModel model = new InfoModel();
		model.setTime(DateUtils.getTruncatedToday());
		//遍历每个业务线，取TOPN 和 当前总量
		for (BusslineEnum bussline : BusslineEnum.values()) {
			if(!BusslineEnum.other.equals(bussline)){
				Map<String, Object> rsMap = Maps.newHashMap();
				//top N
				rsMap.put("data", getTopCateData(null,bussline,count));
				// total
				model.setBussline(bussline.value());
				rsMap.put("total", dao.loadDailySum("infoNum", model));
				resultMap.put(bussline.toString(), rsMap);
			}
		}

		ResumeAddModel rsModel = new ResumeAddModel();
		rsModel.setTime(DateUtils.getTruncatedToday());
		//取简历的 TOPN 和 当前总量
		Map<String, Object> rsMap = Maps.newHashMap();
		rsMap.put("data", getResumeTopCateData(null,count));
		rsMap.put("total", resumeAddDao.loadDailySum("addNum", rsModel));
		resultMap.put("jianli", rsMap);
		
		return JsonUtils.toJson(resultMap);
	}
	
	/**
	 * 获取TOP N
	 */
	private List<ResultPoint> getTopCateData(String platform, BusslineEnum bussline, int count) {
		if (count < 1) {
			count = 1;
		}
		InfoModel model = new InfoModel();
		model.setTime(DateUtils.getTruncatedToday());
		model.setPlatform(StringUtils.isBlank(platform) ? null : platform);
		model.setBussline(bussline != null ? bussline.value() : null);
		Set<Tuple> tuples = dao.loadTopCateList(model, count);
		List<ResultPoint> datas = Lists.newArrayList();
		for (Tuple tuple : tuples) {
			ResultPoint data = new ResultPoint();
			data.setType(tuple.getElement());
			data.setValue((long) tuple.getScore());
			datas.add(data);
		}
		return datas;
	}

	/**
	 * 获取简历TOP N
	 */
	private List<ResultPoint> getResumeTopCateData(String platform,  int count) {
		if (count < 1) {
			count = 1;
		}
		ResumeAddModel model = new ResumeAddModel();
		model.setTime(DateUtils.getTruncatedToday());
		model.setPlatform(StringUtils.isBlank(platform) ? null : platform);
		Set<Tuple> tuples = resumeAddDao.loadTopCateList(model, count);
		List<ResultPoint> datas = Lists.newArrayList();
		for (Tuple tuple : tuples) {
			ResultPoint data = new ResultPoint();
			data.setType(tuple.getElement());
			data.setValue((long) tuple.getScore());
			datas.add(data);
		}
		return datas;
	}
	
	
	private List<InfoModel> createModels(long startTime, long endTime, long interval, long span, String platform, BusslineEnum bussline) {
		long minTime = endTime - span;
		if (startTime == 0 || startTime < minTime) {
			startTime = minTime;
		}

		List<InfoModel> models = Lists.newArrayList();
		for (long i = startTime + interval; i <= endTime; i += interval) {

			InfoModel model = new InfoModel();
			model.setTime(i);
			model.setPlatform(StringUtils.isBlank(platform) ? null : platform);
			model.setBussline(bussline != null ? bussline.value() : null);
			models.add(model);
		}
		return models;
	}

	protected void checkType(String type) {
		if (!types.contains(type)) {
			throw new BusinessException("error type! (%s)", type);
		}
	}

	protected boolean isDiv(String type) {
		return divTypes.contains(type);
	}

	@Override
	public String ping() {
		return "PONG";
	}

	@Override
	public long getCurrentUserCount() {
		return dao.getInfoUserCount();
	}
}
